use std::{slice::from_raw_parts, str::from_utf8_unchecked};

//解引用裸指针
//裸指针长这样: *const T 和 *mut T，它们分别代表了不可变和可变
//可以绕过 Rust 的借用规则，可以同时拥有一个数据的可变、不可变指针，甚至还能拥有多个可变的指针
// 并不能保证指向合法的内存
// 可以是 null
// 没有实现任何自动的回收 (drop)
#[test]
fn test() {
    let mut num = 5;

    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;

    //创建裸指针是安全的行为，而解引用裸指针才是不安全的行为 :
    unsafe {
        println!("r1 is: {}", *r1);
        println!("r2 is: {}", *r2);
    }
}
#[test]
fn test2(){
    //基于地址创建裸指针
    let address = 0x012345usize;
    let r = address as *const i32;
}
// 获取字符串的内存地址和长度
fn get_memory_location() -> (usize, usize) {
    let string = "Hello World!";
    let pointer = string.as_ptr() as usize;
    let length = string.len();
    (pointer, length)
}

// 在指定的内存地址读取字符串
fn get_str_at_location(pointer: usize, length: usize) -> &'static str {
    unsafe { from_utf8_unchecked(from_raw_parts(pointer as *const u8, length)) }
}
#[test]
fn test3() {
    let (pointer, length) = get_memory_location();
    let message = get_str_at_location(pointer, length);
    println!(
        "The {} bytes at 0x{:X} stored: {}",
        length, pointer, message
    );
    // 如果大家想知道为何处理裸指针需要 `unsafe`，可以试着反注释以下代码
    // let message = get_str_at_location(1000, 10);
}

#[test]
fn test4() {
    let a: Box<i32> = Box::new(10);
    // 需要先解引用a
    let b: *const i32 = &*a;
    // 使用 into_raw 来创建
    let c: *const i32 = Box::into_raw(a);
}

//使用 unsafe 声明的函数时，一定要看看相关的文档，确定自己没有遗漏什么。
